import logging
import os
import sys
import threading
from logging import FileHandler


def get_caller_info():
    frame = sys._getframe(3)
    while hasattr(frame, "f_code"):
        filename = os.path.basename(frame.f_code.co_filename)
        if filename != os.path.basename(__file__):  # 避免获取当前文件名
            lineno = frame.f_lineno
            return filename, lineno
        frame = frame.f_back
    return "unknown file", 0


class CustomLogger:
    """
    A custom logger class for logging messages to console and/or file with different log levels.

    Args:
        logger_name (str): The name of the logger.
        console_level (int, optional): The log level for console logging. Defaults to logging.DEBUG.
        file_level (int, optional): The log level for file logging. Defaults to logging.DEBUG.
    """
    
    _local = threading.local()

    def __init__(self, logger_name='custom_logger', min_level=logging.DEBUG, console_level=logging.INFO, file_level=logging.DEBUG):
        self.logger_name = logger_name
        self.console_level = console_level
        self.file_level = file_level
        self.log_file = None
        self.min_level = min_level
        self._init_logger()  # 调用初始化方法

    def _init_logger(self):
        self.logger = logging.getLogger(self.logger_name)
        self.logger.setLevel(self.min_level)

        console_formatter = logging.Formatter('[%(asctime)s] [%(levelname)-8s] [%(name)s]: %(message)s')
        file_formatter = logging.Formatter('[%(asctime)s] [%(levelname)-8s] [%(name)s]: %(message)s')

        # 添加控制台处理程序，如果它还不存在
        if not any(isinstance(handler, logging.StreamHandler) for handler in self.logger.handlers):
            console_handler = logging.StreamHandler()
            console_handler.setLevel(self.console_level)
            console_handler.setFormatter(console_formatter)
            self.logger.addHandler(console_handler)

        # 添加文件处理程序，如果它还不存在
        if self.log_file and not any(isinstance(handler, logging.FileHandler) for handler in self.logger.handlers):
            file_handler = logging.FileHandler(self.log_file, encoding='utf-8')
            file_handler.setLevel(self.file_level)
            file_handler.setFormatter(console_formatter)
            self.logger.addHandler(file_handler)


    def set_log_file(self, log_file="leetcode_automation.log"):
        """
        Set the log file for file logging.

        Args:
            log_file (str): The path to the log file.
        """
        # with open(log_file, 'w', encoding='utf-8') as f:
        #     print("initialize log file")
        #     pass
        self.log_file = log_file
        self._init_logger()


    def _log(self, level, msg, *args, **kwargs):
        filename, lineno = get_caller_info()
        custom_msg = f'[{filename}:{lineno}] {msg}'
        self.logger.log(level, custom_msg, *args, **kwargs)

    def debug(self, msg, *args, **kwargs):
        self._log(logging.DEBUG, msg, *args, **kwargs)

    def info(self, msg, *args, **kwargs):
        self._log(logging.INFO, msg, *args, **kwargs)

    def warning(self, msg, *args, **kwargs):
        self._log(logging.WARNING, msg, *args, **kwargs)

    def error(self, msg, *args, **kwargs):
        self._log(logging.ERROR, msg, *args, **kwargs)

    def critical(self, msg, *args, **kwargs):
        self._log(logging.CRITICAL, msg, *args, **kwargs)
